#!/usr/bin/env node
/**
 * 生成文档脚本
 * 功能：根据core/src目录中的工具函数，动态生成api文档
 * 支持指定单个文件生成文档：pnpm run docs:generate -- path/to/file.ts
 */
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const rootDir = path.join(__dirname, '..');

// 配置
const UTILS_DIR = path.join(rootDir, 'packages/core/src');
const DOCS_API_DIR = path.join(rootDir, 'packages/docs/api');

// 解析命令行参数，获取指定的文件路径
const args = process.argv.slice(2);
let targetFilePath = null;
if (args.length > 0 && args[0].endsWith('.ts')) {
  targetFilePath = args[0];
  // 如果是相对路径，则转换为绝对路径
  if (!path.isAbsolute(targetFilePath)) {
    targetFilePath = path.resolve(process.cwd(), targetFilePath);
  }
}

/**
 * 动态获取工具分类列表
 * @returns {string[]} 分类目录名数组
 */
function getCategories() {
  try {
    const entries = fs.readdirSync(UTILS_DIR, { withFileTypes: true });
    return entries.filter((entry) => entry.isDirectory()).map((dir) => dir.name);
  } catch (error) {
    console.error('❌ 获取工具分类失败:', error);
    return [];
  }
}

// 动态获取分类列表
const CATEGORIES = getCategories();

/**
 * 解析JSDoc注释，提取title、description、params和returns
 */
function parseJSDoc(comment) {
  if (!comment) return { title: '', description: '', params: [], returns: '' };

  const lines = comment
    .split('\n')
    .map((line) => line.replace(/^\s*\*\s?/, '').trim())
    .filter((line) => line);

  let title = '';
  let description = '';
  let inDescription = false;

  // 提取@param标签信息
  const params = [];

  // 提取@returns标签信息
  let returns = '';

  for (const line of lines) {
    // console.log('line', line);
    if (line.startsWith('@description')) {
      // 提取@description标签后的内容
      description += line.replace('@description', '').trim() + ' ';
      inDescription = true;
    } else if (inDescription && !line.startsWith('@')) {
      // 继续收集@description的内容，直到遇到下一个标签
      description += line + ' ';
    } else if (!title && !line.startsWith('@')) {
      // 如果还没有标题，且这行不是标签，则认为是标题
      title = line;
    } else if (line.startsWith('@param')) {
      inDescription = false;

      // 匹配格式 @param {type} name - description
      let paramMatch = line.match(/@param\s+\{(.*?)\}\s+(\w+)(?:\s*\-\s*(.*))?/);
      // console.log('paramMatch1', paramMatch);
      // 如果上面的正则匹配不出参数名或者描述，尝试更精确地匹配嵌套对象参数格式
      if (!paramMatch[3]?.trim() || !paramMatch[2]?.trim()) {
        // 匹配格式 @param {type} name.key - description
        paramMatch = line.match(/@param\s+\{(.*?)\}\s+(\w+\.\w+)\s*\-\s*(.*)/);
      }
      // console.log('paramMatch2', paramMatch);
      if (paramMatch) {
        params.push({
          type: paramMatch[1]?.trim() || '*',
          name: paramMatch[2]?.trim() || '',
          description: paramMatch[3]?.trim() || ''
        });
      }
    } else if (line.startsWith('@returns') || line.startsWith('@return')) {
      inDescription = false;

      // 匹配格式 @returns {type} 描述文本 或 @returns {type} - 描述文本
      let returnsMatch = line.match(/@(?:returns|return)\s+\{(.*?)\}\s*(-\s*)?(.*)?/);
      if (returnsMatch) {
        // 保存包含类型和描述的完整返回信息
        returns = returnsMatch[1]?.trim() || '';
        if (returnsMatch[3]?.trim()) {
          // 可以选择将类型和描述一起保存，或者分别保存
          returns = `{${returns}} ${returnsMatch[3].trim()}`;
        }
      }
    } else if (line.startsWith('@')) {
      // 遇到其他标签，结束description的收集
      inDescription = false;
    }
  }

  return {
    title: title.trim(),
    description: description.trim(),
    params,
    returns
  };
}

/**
 * 提取TypeScript函数信息
 */
function extractFunctionInfo(filePath, category) {
  // console.log('filePath:', filePath, 'category:', category);
  const content = fs.readFileSync(filePath, 'utf-8');
  const fileName = path.basename(filePath, '.ts');

  // 简单的AST解析来提取函数信息
  const functionMatch = content.match(/export\s+(async\s+)?(function|const)\s+(\w+)/);
  // console.log('functionMatch', functionMatch);
  if (!functionMatch) return null;

  const functionName = functionMatch[3];
  // 从JSDoc注释中提取有用信息
  const jsDocMatch = content.match(/\/\*\*([\s\S]*?)\*\//);
  const jsDocInfo = jsDocMatch ? parseJSDoc(jsDocMatch[1]) : { title: '', description: '', params: [], returns: '' };
  // 提取示例代码
  const exampleMatch = content.match(/@example\s*\n\s*\*\s*([\s\S]*?)(?=\n\s*\*\/)/);
  const example = exampleMatch ? exampleMatch[1].trim() : '';

  return {
    name: functionName,
    title: jsDocInfo.title,
    description: jsDocInfo.description,
    params: jsDocInfo.params,
    returns: jsDocInfo.returns,
    example,
    fileName,
    category
  };
}

/**
 * 生成分类的文档数据
 */
function generateCategoryData(category) {
  const categoryDir = path.join(UTILS_DIR, category);
  const files = fs
    .readdirSync(categoryDir)
    .filter((file) => file.endsWith('.ts') && !file.endsWith('_md.json') && !file.endsWith('index.ts'));

  const functions = files
    .map((file) => {
      const filePath = path.join(categoryDir, file);

      return extractFunctionInfo(filePath, category);
    })
    .filter(Boolean);

  return functions;
}

/**
 * 生成JSON文档数据
 */
function generateJSONData() {
  const allData = {};

  // 如果指定了单个文件，则只处理该文件
  if (targetFilePath) {
    // 检查文件是否在UTILS_DIR下
    if (!targetFilePath.startsWith(UTILS_DIR)) {
      console.error(`❌ 指定的文件不在core/src目录下: ${targetFilePath}`);
      return allData;
    }

    // 提取分类和文件信息
    const relativePath = path.relative(UTILS_DIR, targetFilePath);
    const pathParts = relativePath.split(path.sep);
    const category = pathParts[0];

    if (!category || !pathParts[1]) {
      console.error(`❌ 文件路径格式不正确: ${targetFilePath}`);
      return allData;
    }

    // 为单个文件生成文档数据
    const funcInfo = extractFunctionInfo(targetFilePath, category);
    if (funcInfo) {
      if (!allData[category]) {
        allData[category] = [];
      }
      allData[category].push(funcInfo);
      console.log(`✅ 已处理单个文件: ${relativePath}`);
    }
  } else {
    // 处理所有分类
    CATEGORIES.forEach((category) => {
      const data = generateCategoryData(category);
      allData[category] = data;
    });
  }

  return allData;
}

/**
 * 生成Markdown文档
 */
function generateMarkdownDocs(data) {
  Object.entries(data).forEach(([category, functions]) => {
    let mdContent = `# ${category.charAt(0).toUpperCase() + category.slice(1)}\n\n`;

    functions.forEach((func) => {
      mdContent += `## ${func.name}\n\n`;
      if (func.title) {
        mdContent += `${func.title}\n\n`;
      }
      if (func.description) {
        mdContent += `${func.description}\n\n`;
      }

      // 生成参数表格
      if (Array.isArray(func.params) && func.params.length > 0) {
        mdContent += `### 参数\n`;
        mdContent += `| 参数 | 类型 | 描述 |\n`;
        mdContent += `| --- | --- | --- |\n`;

        func.params.forEach((param) => {
          mdContent += `| ${param.name.replace(/\|/g, '\\|')} | ${param.type.replace(/\|/g, '\\|')} | ${param.description.replace(/\|/g, '\\|') || ''} |\n`;
        });

        mdContent += `\n`;
      }

      mdContent += `### 返回\n\`\`\`plaintext\n${func.returns}\n\`\`\`\n\n`;

      if (func.example) {
        // 清理示例代码中的多余星号和空格
        const cleanExample = func.example.replace(/^\s*\*\s?/gm, '');
        mdContent += `### 示例\n${cleanExample}\n\n`;
      }
    });

    const mdPath = path.join(DOCS_API_DIR, `${category}.md`);
    fs.writeFileSync(mdPath, mdContent);
  });
}

/**
 * 更新主索引文件
 */
function updateIndexFile(data) {
  let indexContent = `# 工具列表\n\n`;

  Object.entries(data).forEach(([category, functions]) => {
    indexContent += `## ${category.charAt(0).toUpperCase() + category.slice(1)}\n\n`;

    functions.forEach((func) => {
      // 使用title作为索引描述，如果没有title则使用description
      const indexDesc = func.title || func.description;
      indexContent += `- [${func.name}](./${category}.md#${func.name.toLowerCase()}) - ${indexDesc}\n`;
    });

    indexContent += `\n`;
  });

  const indexPath = path.join(DOCS_API_DIR, 'index.md');
  fs.writeFileSync(indexPath, indexContent);
}

// 主函数
function main() {
  console.log('🚀 开始生成文档...');

  // 显示是否指定了单个文件
  if (targetFilePath) {
    console.log(`🎯 正在为指定文件生成文档: ${path.relative(rootDir, targetFilePath)}`);
  } else {
    console.log('📂 正在为所有工具函数生成文档...');
  }

  try {
    // 中间数据
    const data = generateJSONData();

    // 如果有数据，则生成文档
    if (Object.keys(data).length > 0) {
      // 生成Markdown文档
      generateMarkdownDocs(data);
      // 更新索引文件
      updateIndexFile(data);
    }

    console.log('🎉 文档生成完成！');
  } catch (error) {
    console.error('❌ 文档生成失败:', error);
    process.exit(1);
  }
}

main();
